package com.gw.booking.service;


import com.gw.booking.common.Constant;
import com.gw.booking.entity.Attachment;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import config.Config;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;
import java.util.UUID;

@Service
public class AttachmentService {
    @Autowired
    SessionFactory sessionFactory;

    /**
     * 上传文件
     *
     * @throws IOException
     * @throws IllegalStateException
     */
    public String txUpload(MultipartFile multipartFile) throws IllegalAccessException, InvocationTargetException, IllegalStateException, IOException {
        String filename = "";
        Session session = sessionFactory.getCurrentSession();

        //保存文件
        filename = saveFile(multipartFile);

        //插入附件表
        addAttachment(session, filename, multipartFile);

        return filename;
    }

    /**
     * 上传临时文件
     *
     * @throws IOException
     * @throws IllegalStateException
     */
    public String txUploadTmp(MultipartFile multipartFile) throws IllegalAccessException, InvocationTargetException, IllegalStateException, IOException {
        String filename = "";
        Session session = sessionFactory.getCurrentSession();

        //保存文件
        filename = saveTmpFile(multipartFile);

        //插入附件表
        addAttachment(session, filename, multipartFile);

        return filename;
    }

    private void addAttachment(Session session, String filename, MultipartFile multipartFile) {
        Attachment attachment = new Attachment();
        attachment.setFilename(filename);
        attachment.setFilenameOriginal(multipartFile.getOriginalFilename());
        attachment.setMime(multipartFile.getContentType());
        attachment.setCreatedAt(new Timestamp(System.currentTimeMillis()));

        session.save(attachment);
    }

    public void clearTmpFiles() {
        File tmp = new File(Config.attachFolder + Config.tmpFolder);
        File[] files = tmp.listFiles();
        for (File file : files) {
            if (file.lastModified() < System.currentTimeMillis() - Constant.ONE_DAY) {
                file.delete();
            }
        }
    }

    public Attachment getAttachment(String filename) {
        Session session = sessionFactory.getCurrentSession();

        return (Attachment) session.createCriteria(Attachment.class).add(Restrictions.eq("filename", filename)).uniqueResult();
    }

    /**
     * 生成文件名
     */
    private String genFileName(String filenameOriginal) {
        String extension = filenameOriginal.substring(filenameOriginal.lastIndexOf("."));
        return genFileNameByExt(extension);
    }

    /**
     * 生成文件名
     */
    public String genFileNameByExt(String extension) {
        return UUID.randomUUID().toString() + extension;
    }

    public File getFile(String filename) {
        File file = new File(Config.attachFolder + filename);
        file.getParentFile().mkdirs();


        return file;
    }

	/**
	 * 移动临时
	 * @param session
	 * @return
	 */
	public String moveTmpFile(Session session, String filename) throws IOException {
		return moveTmpFile(session, filename, "");
	}

	/**
	 * 移动临时
	 * @param session
	 * @return
	 */
	public String moveTmpFile(Session session, String filename, String destFold) throws IOException {
		if (StringUtils.isEmpty(filename)
				|| !filename.startsWith(Config.tmpFolder)) {
			return filename;
		}

//		// 创建目录
//		new File(Config.attachFolder + destFold).mkdirs();
//
//		String regularFilename = destFold + filename.replace(Config.tmpFolder, "");
//		new File(Config.attachFolder + filename).renameTo(new File(Config.attachFolder + regularFilename));
//
//		Attachment attachment = getAttachment(filename);
//		if (attachment != null) {
//			attachment.setFilename(regularFilename);
//			session.update(attachment);
//			session.flush();
//		}
		// 创建目录
		new File(Config.attachFolder + destFold).mkdirs();

		String regularFilename = destFold + filename.replace(Config.tmpFolder, "");

        // 读取原文件
// 部分图片由于格式问题ImageIO.read()会出错,需处理一下
//        JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new FileInputStream(Config.attachFolder + filename));
//        BufferedImage bufImg = decoder.decodeAsBufferedImage();

		File srcFile = new File(Config.attachFolder + filename);
		BufferedImage bufImg = ImageIO.read(srcFile);
		Integer width = 800;
		// 文件宽度过大则等比例缩小
		if (bufImg.getWidth() > width) {
			String fileNameNew = Config.attachFolder + regularFilename;
			File destFile = new File(fileNameNew);
			double hr = width * 1.0 / bufImg.getWidth();
			int height = (int) (bufImg.getHeight() * hr);
			Image image = bufImg.getScaledInstance(width, height, bufImg.SCALE_SMOOTH);
			AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(hr, hr), null);
			image = ato.filter(bufImg, null);
			ImageIO.write((BufferedImage) image, fileNameNew.substring(fileNameNew.lastIndexOf(".") + 1), destFile); //写入缩减后的图片

		} else {
			new File(Config.attachFolder + filename).renameTo(new File(Config.attachFolder + regularFilename));
		}

		Attachment attachment = getAttachment(filename);
		if (attachment != null) {
			attachment.setFilename(regularFilename);
			session.update(attachment);
			session.flush();
		}

		return regularFilename;
	}

    /**
     * 保存附件
     *
     * @throws IOException
     * @throws IllegalStateException
     */
    private String saveFile(MultipartFile multipartFile) throws IllegalStateException, IOException {
        String filenameOriginal = multipartFile.getOriginalFilename();
        String filename = genFileName(filenameOriginal);

        File target = getFile(filename);

        multipartFile.transferTo(target);

        return filename;
    }

    /**
     * 保存附件
     *
     * @throws IOException
     * @throws IllegalStateException
     */
    private String saveTmpFile(MultipartFile multipartFile) throws IllegalStateException, IOException {
        String filenameOriginal = multipartFile.getOriginalFilename();
        String filename = Config.tmpFolder + genFileName(filenameOriginal);

        File target = getFile(filename);

        multipartFile.transferTo(target);

        return filename;
    }
}
